#include "StdAfx.h"
#include ".\texture.h"

CTexture::CTexture(void):
m_nID(0),
m_pImage(NULL),
m_nWidth(-1),
m_nHeight(-1),
m_nBpp(-1)
{
}

CTexture::~CTexture(void)
{
}

BOOL CTexture::LoadTexture(wstring strFileName)
{
	if (m_nID > 0) return FALSE;
	if (m_pImage != NULL) return FALSE;
	m_pImage = ReadImageFile(strFileName, m_nWidth, m_nHeight ,m_nBpp);
	if (m_pImage == NULL) return FALSE;

	GLint nInternalFormat;
	GLenum nFormat;
	if (!GetGLFormat(m_pixelFormat, nInternalFormat, nFormat)) return FALSE;

	glGenTextures(1, &m_nID);
	if (m_nID <= 0) return FALSE;
	glBindTexture(GL_TEXTURE_2D, m_nID);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexImage2D(GL_TEXTURE_2D, 0, nInternalFormat, m_nWidth, m_nHeight, 0, nFormat, GL_UNSIGNED_BYTE, m_pImage);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	delete m_pImage;
	m_pImage = NULL;
	return TRUE;
}

BYTE* CTexture::ReadImageFile(wstring strFileName, int& nWidth, int& nHeight, int& nBpp)
{
	Gdiplus::Bitmap oBitmap(strFileName.c_str() );
	if (oBitmap.GetWidth() <= 0 || oBitmap.GetHeight() <= 0) return NULL;

	nWidth = oBitmap.GetWidth();
	nHeight = oBitmap.GetHeight();

	m_pixelFormat = oBitmap.GetPixelFormat();
	nBpp = GetBitCount(m_pixelFormat);

	BYTE *pImgData = new BYTE[nWidth*nHeight*nBpp];

	Gdiplus::BitmapData oBitmapData;
	Gdiplus::Rect rect(0, 0, nWidth, nHeight);

	oBitmap.LockBits(
		&rect,
		Gdiplus::ImageLockModeRead,
		m_pixelFormat,
		&oBitmapData);

	memcpy(pImgData, oBitmapData.Scan0, nWidth*nHeight*sizeof(BYTE)*nBpp);
	oBitmap.UnlockBits(&oBitmapData);

	return pImgData;
}

int CTexture::GetBitCount(Gdiplus::PixelFormat pixelFormate)
{
	int nBitCount = 0;

	switch(pixelFormate)
	{
	case PixelFormatUndefined:
	case PixelFormat1bppIndexed:
	case PixelFormat4bppIndexed:
		nBitCount = 0;
		break;
	case PixelFormat8bppIndexed:
		nBitCount = 1;
		break;
	case PixelFormat16bppGrayScale:
	case PixelFormat16bppRGB555:
	case PixelFormat16bppARGB1555:
		nBitCount = 2;
		break;
	case PixelFormat24bppRGB:
		nBitCount = 3;
		break;
	case PixelFormat32bppRGB:
	case PixelFormat32bppARGB:
	case PixelFormat32bppPARGB:
		nBitCount = 4;
		break;
	case PixelFormat48bppRGB:
		nBitCount = 6;
		break;
	case PixelFormat64bppARGB:
	case PixelFormat64bppPARGB:
		nBitCount = 8;
		break;
	default:
		break;
	}
	return nBitCount;
}

BOOL CTexture::GetGLFormat(IN Gdiplus::PixelFormat pixelFormate, OUT GLint& internalFormat, OUT GLenum& format)
{
	switch(pixelFormate)
	{
	case PixelFormatUndefined:
	case PixelFormat1bppIndexed:
	case PixelFormat4bppIndexed:
		return FALSE;

	case PixelFormat8bppIndexed:
		internalFormat = GL_COLOR_INDEX;
		format = GL_COLOR_INDEX;
		break;

	case PixelFormat16bppGrayScale:
		internalFormat = GL_LUMINANCE16;
		format = GL_LUMINANCE;
		break;

	case PixelFormat16bppRGB555:
		internalFormat = GL_RGB5;
		format = GL_BGR_EXT;
		break;

	case PixelFormat16bppARGB1555:
		internalFormat = GL_RGB5_A1;
		format = GL_BGRA_EXT;
		break;

	case PixelFormat24bppRGB:
		internalFormat = GL_RGB;
		format = GL_BGR_EXT;
		break;

	case PixelFormat32bppRGB:
	case PixelFormat32bppARGB:
	case PixelFormat32bppPARGB:
		internalFormat = GL_RGBA;
		format = GL_BGRA_EXT;
		break;

	case PixelFormat48bppRGB:
		internalFormat = GL_RGB16;
		format = GL_BGR_EXT;
		break;

	case PixelFormat64bppARGB:
	case PixelFormat64bppPARGB:
		internalFormat = GL_RGBA16;
		format = GL_BGRA_EXT;
		break;

	default:
		return FALSE;
	}

	return TRUE;
}
